/*
 * @Author: moeWang
 * @Date: 2022-03-08 14:17:32
 * @LastEditTime: 2022-03-08 16:50:19
 * @LastEditors: moeWang
 * @Description:
 * @FilePath: \nest-web\src\logical\menu\service\menu.service.ts
 */

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { TSVECTOR } from 'sequelize/types';
import ModelManager from 'sequelize/types/model-manager';
import { BaseService } from 'src/logical/common/services/base.service';
import { RoleMenuEntity } from 'src/logical/role/entity/role.entity';
import { RoleService } from 'src/logical/role/service/role.service';
import { MenuEntity } from '../entity/menu.entity';
import { MenuResultModel } from '../models/menu.model';

@Injectable()
export class MenuService extends BaseService {
  constructor(
    @InjectModel(MenuEntity)
    private readonly menuEntity: typeof MenuEntity,
    private readonly roleService: RoleService,
  ) {
    super();
  }

  async findAllIdsByRolesRoleId(role) {
    const menuIdEntityList = await RoleMenuEntity.findAll({
      where: {
        roleId: role,
      },
    });
    return menuIdEntityList.map((item) => {
      return item.get('menuId');
    });
    // console.log(menuIdList);
  }

  async findById(id) {
    return await MenuEntity.findByPk(id);
  }

  async get(tokenInfo) {
    const roles = await this.roleService.findRoleIdByAccountId(
      tokenInfo.accountId,
    );
    const rolesList = roles.map((item) => {
      return item.get('roleId');
    });
    const menuEntityList = [];
    let menuIdList = [];
    for (let i = 0; i < rolesList.length; i++) {
      const role = rolesList[i];

      const menuIds = await this.findAllIdsByRolesRoleId(role);
      menuIdList.push(...menuIds);
    }
    menuIdList = Array.from(new Set(menuIdList));

    for (let i = 0; i < menuIdList.length; i++) {
      const id = menuIdList[i];
      menuEntityList.push(await (await this.findById(id)).get());
    }

    for (let i = 0; i < menuEntityList.length; i++) {
      const m_i = menuEntityList[i];
      //判断是否为根节点，不是根节点继续
      if (m_i.menuPId) {
        let flag: boolean = true; //是否需要补充上级节点

        for (let j = 0; j < menuEntityList.length; j++) {
          const m_j = menuEntityList[j];
          //当前节点的上级节点在列表中
          if (m_j.menuId === m_i.menuPId) {
            flag = false;
          }
        }
        if (flag) {
          const item = await (await this.findById(m_i.menuPId)).get();
          menuEntityList.splice(i, 0, item);
          i--;
        }
      }
    }

    const rs = [];

    for (let i = 0; i < menuEntityList.length; i++) {
      const entity = menuEntityList[i];
      if (!entity.menuPId) {
        const node = new MenuResultModel();
        this.copyEntityToModel(entity, node);

        this.quickSort(this.findChildren(node, menuEntityList), rs);
      }
    }

    return this.resultData(rs, 200, '');
  }

  findChildren(node, menuEntityList) {
    for (let i = 0; i < menuEntityList.length; i++) {
      const t = menuEntityList[i];

      if (!t.menuPId) {
        continue;
      }
      const temp = [];
      if (node.id === t.menuPId) {
        if (!node.children) {
          node.children = [];
        }

        const childNode = new MenuResultModel();
        this.copyEntityToModel(t, childNode);
        temp.push(childNode);
        this.quickSort(
          this.findChildren(childNode, menuEntityList),
          node.children,
        );
      }
    }
    return node;
  }

  quickSort(temp, rs) {
    if (rs.length) {
      for (let i = 0; i < rs.length; i++) {
        if (temp.sort < rs[i].sort) {
          rs.splice(i, 0, temp);
          i++;
          return;
        }
      }
    }
    rs.push(temp);
  }

  copyEntityToModel(entity, node) {
    node.id = entity.menuId;
    node.icon = entity.icon;
    node.label = entity.menuName;
    node.path = entity.menuCode;
    node.hidden = false;
    node.sort = entity.sort;
  }
}
